package org.boot.easyapi.permission.service.impl;

import org.boot.easyapi.enums.permission.TypeEnum;
import org.boot.easyapi.expand.AuthenticationUserInfoAbstractInterface;
import org.boot.easyapi.permission.dao.PermissionRepository;
import org.boot.easyapi.permission.entity.PermissionDO;
import org.boot.easyapi.permission.service.PermissionService;
import org.boot.easyapi.permission.util.RequestPathUtil;
import org.boot.easyapi.util.spring.SpringUtil;
import org.boot.easyapi.util.web.AuthenticationUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PermissionServiceImpl implements PermissionService {

    @Resource
    private PermissionRepository permissionRepository;

    @Override
    public void insert(PermissionDO p) {
        permissionRepository.insert(p);
    }

    @Override
    public void update(PermissionDO p) {
        permissionRepository.updateAllById(p);
    }

    @Override
    public void delete(Long id) {
        permissionRepository.deleteById(id);
    }

    @Override
    public PermissionDO findById(Long id) {
        return permissionRepository.selectById(id);
    }

    @Override
    public List<PermissionDO> findList(PermissionDO permission) {
       return permissionRepository.selectList(permission);
    }

    @Override
    public void insertDefaultPathRule(PermissionDO permissionDO) {
        permissionDO.setStatus(0);
        permissionDO.setDefaultPath(0);
        permissionDO.setType(TypeEnum.PATH.getKey());
        this.insert(permissionDO);
    }

    @Override
    public void insertPathRule(PermissionDO permissionDO) {
        permissionDO.setStatus(0);
        permissionDO.setDefaultPath(1);
        permissionDO.setType(TypeEnum.PATH.getKey());
        this.insert(permissionDO);
    }

    @Override
    public void insertIpRule(PermissionDO permissionDO) {
        permissionDO.setStatus(0);
        permissionDO.setType(TypeEnum.IP.getKey());
        this.insert(permissionDO);
    }

    @Override
    public boolean hasPathPermission(HttpServletRequest request) {
        PermissionDO permissionDO = new PermissionDO();
        permissionDO.setStatus(0);
        permissionDO.setType(TypeEnum.PATH.getKey());
        List<PermissionDO> list = permissionRepository.selectList(permissionDO);
        if (list.isEmpty()) return false;

        //当前请求路径
        String requestPath = RequestPathUtil.getPathAfterPort(request.getRequestURL().toString());

        //过滤出默认放行路径
        List<PermissionDO> defaultPathList = filterPathList(list, 0);
        if (!defaultPathList.isEmpty()){
            for (PermissionDO defaultPath : defaultPathList) {
                if(RequestPathUtil.isMatch(defaultPath.getPath(), requestPath)) return true;
            }
        }

        //过滤出权限控制路径
        List<PermissionDO> pathList = filterPathList(list, 1);
        if (!pathList.isEmpty()){
            for (PermissionDO path : pathList) {
                if(RequestPathUtil.isMatch(path.getPath(), requestPath)) {
                    AuthenticationUserInfoAbstractInterface bean = SpringUtil.getBean(AuthenticationUserInfoAbstractInterface.class);
                    if(bean != null){
                        return bean.hasPermission(request, AuthenticationUtil.getAuthenticationUserInfo(), path.getPathMenuJson(), path.getPathRoleJson());
                    }
                }
            }
        }

        return false;
    }

    @Override
    public boolean hasIpPermission(HttpServletRequest request) {
        //检测该ip是否为白名单
        PermissionDO permissionDO = new PermissionDO();
        permissionDO.setStatus(0);
        permissionDO.setType(TypeEnum.IP.getKey());
        permissionDO.setIp(request.getRemoteAddr());
        return !permissionRepository.selectList(permissionDO).isEmpty();
    }

    private List<PermissionDO> filterPathList(List<PermissionDO> list, Integer defaultPath){
        return list.stream().filter(p -> p.getDefaultPath().equals(defaultPath)).collect(Collectors.toList());
    }


}
